package org.snail.proxy.client;

import com.google.common.collect.Lists;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapDLT;
import org.jnetpcap.PcapIf;
import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.protocol.network.Ip4;
import org.jnetpcap.protocol.tcpip.Http;

import java.net.UnknownHostException;
import java.util.List;

public class Netcap {
    public static void main(String[] args) {
        List<PcapIf> devs = Lists.newLinkedList();
        StringBuilder errorBuilder = new StringBuilder();
        int result = Pcap.findAllDevs(devs, errorBuilder);
        System.out.println(result);
        devs.forEach(System.out::println);
        System.out.println(errorBuilder);
        Pcap pcap = null;
        for (PcapIf dev : devs) {
            errorBuilder.setLength(0);
            pcap = Pcap.openLive(dev.getName(), 64, Pcap.MODE_PROMISCUOUS, 1000, errorBuilder);
            if (pcap == null) {
                System.out.println("open error " + dev.getName() + ": " + errorBuilder);
            } else if (pcap.datalink() == PcapDLT.EN10MB.getValue() && (dev.getFlags() == 0 || dev.getFlags() == 30)) {
                System.out.println("open " + dev.getName() + ": " + errorBuilder);
            } else {
                pcap.close();
                pcap = null;
            }
        }
        if (pcap == null) {
            System.out.println("Not found dev.");
        } else {
            final Pcap sender = pcap;
            errorBuilder.setLength(0);
            result = pcap.setNonBlock(Pcap.MODE_BLOCKING, errorBuilder);
            System.out.println("setNonBlock: " + result + ", " + errorBuilder);
            pcap.loop(Pcap.LOOP_INFINITE, (PcapPacket packet, String text) -> {
//                System.out.println("text: " + text);
                if (packet.hasHeader(Http.ID)) {
//                    Http http = new Http();
//                    packet.getHeader(http);
//                    System.out.println("http packet: " + http + "\n" + "payload: " + new String(http.getPayload()));
                    Ip4 ip4 = new Ip4();
                    packet.getHeader(ip4);
                    try {
                        if (!isLocal(ip4.destination())) {
                            System.out.println("ip4 packet: " + toIp(ip4.destination()) + ip4 + "\n" + "payload: " + new String(ip4.getPayload()));
                            ip4.destination(toIp("43.129.241.168"));
//                            sender.sendPacket(packet);
                        }
                    } catch (NullPointerException e) {

                    }
                }
            }, "xuxd");
        }
    }

    private static String toIp(byte[] data) {
        StringBuilder builder = new StringBuilder();
        for (byte d : data) {
            builder.append(d & 0xFF).append('.');
        }
        builder.setLength(builder.length() - 1);
        return builder.toString();
    }

    private static boolean isLocal(byte[] data) {
        try {
            String ip = toIp(data);
            return DSystem.getNWIP().equals(ip) || "43.129.241.168".equals(ip);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return false;
        }
    }

    private static byte[] toIp(String ip) {
        String[] segments = ip.split("\\.");
        byte[] data = new byte[segments.length];
        for (int i = 0;i < segments.length;i++) {
            data[i] = (byte) Integer.parseInt(segments[i]);
        }
        return data;
    }
}
